package lock

import (
	"fmt"
	"sync"
	"sync/atomic"
	"time"
)

// SpinLock 定义自旋锁结构体
type SpinLock struct {
	locked int32
}

// Lock 方法用于获取锁
func (s *SpinLock) Lock() {
	for !atomic.CompareAndSwapInt32(&s.locked, 0, 1) {
		// 如果没有成功获取到锁，则让出CPU时间片，避免CPU占用过高
		time.Sleep(time.Microsecond)
	}
}

func (s *SpinLock) UnLock() {
	// 使用原子操作将 locked 设置为 0，表示释放锁
	atomic.StoreInt32(&s.locked, 0)
}

func TrySpinLock() {
	// 创建一个 SpinLock 实例
	var spinLock SpinLock
	// 用于存储协程执行完成的信号
	wg := &sync.WaitGroup{}

	// 启动两个协程来模拟并发场景
	for i := 0; i < 2; i++ {
		wg.Add(1)
		go func(id int) {
			defer wg.Done()
			// 获取锁
			spinLock.Lock()
			fmt.Printf("协程 %d 已获取到锁\n", id)
			// 模拟一些工作
			time.Sleep(2 * time.Second)
			fmt.Printf("协程 %d 即将释放锁\n", id)
			spinLock.UnLock()
		}(i)
	}

	// 等待两个协程都执行完成
	wg.Wait()

	fmt.Println("所有协程执行完毕")
}
